import * as compiler from '@vue/compiler-sfc';
import { ComponentProp, ComponentEvent, ComponentSlot, ComponentEventArgument, ComponentSlotBinding } from '../../core/types';
import { CommentUtils } from './CommentUtils';
import { TypeUtils } from './TypeUtils';
import { parse } from '@babel/parser';
import traverse from '@babel/traverse';
import * as t from '@babel/types';

/**
 * 使用compiler-sfc和AST解析进行Vue组件属性提取的工具类
 */
export class CompilerSfcPropertyExtractor {
  /**
   * 通过compiler-sfc解析Vue单文件组件
   * @param content 组件内容
   * @param filename 文件名
   * @returns 解析后的SFC描述符
   */
  public static parseSFC(content: string, filename: string): compiler.SFCDescriptor {
    const { descriptor } = compiler.parse(content, { filename });
    return descriptor;
  }

  /**
   * 提取组件Props
   * @param descriptor Vue SFC描述符
   * @returns 组件Props列表
   */
  public static extractProps(descriptor: compiler.SFCDescriptor): ComponentProp[] {
    const props: ComponentProp[] = [];
    const scriptContent = descriptor.script?.content || descriptor.scriptSetup?.content || '';
    
    if (!scriptContent) {
      return props;
    }

    try {
      // 使用Babel解析脚本内容
      const ast = parse(scriptContent, {
        sourceType: 'module',
        plugins: ['typescript', 'jsx']
      });

      // 遍历AST寻找props定义
      traverse(ast, {
        // 处理Vue 3 Composition API的defineProps
        CallExpression(path) {
          if (t.isIdentifier(path.node.callee) && path.node.callee.name === 'defineProps') {
            // defineProps<{ ... }>() 类型定义
            if (path.node.typeParameters && t.isTSTypeParameterInstantiation(path.node.typeParameters)) {
              const typeAnnotation = path.node.typeParameters.params[0];
              if (t.isTSTypeLiteral(typeAnnotation)) {
                typeAnnotation.members.forEach(member => {
                  if (t.isTSPropertySignature(member) && t.isIdentifier(member.key)) {
                    const propName = member.key.name;
                    let propType = 'any';
                    let required = true;
                    let values: string[] = [];
                    
                    // 检查可选属性
                    if (member.optional) {
                      required = false;
                    }
                    
                    // 提取类型
                    if (member.typeAnnotation) {
                      propType = scriptContent.substring(
                        member.typeAnnotation.start || 0, 
                        member.typeAnnotation.end || 0
                      ).replace(/^:\s*/, '');

                      // 从类型中提取可能的枚举值
                      if (t.isTSTypeAnnotation(member.typeAnnotation) && 
                          t.isTSUnionType(member.typeAnnotation.typeAnnotation)) {
                        values = CompilerSfcPropertyExtractor.extractEnumValuesFromUnionType(member.typeAnnotation.typeAnnotation, scriptContent);
                      }
                    }
                    
                    // 查找属性描述（从注释）
                    const propDescription = CompilerSfcPropertyExtractor.findPropDescriptionFromAST(member, scriptContent);
                    
                    props.push({
                      name: propName,
                      type: propType,
                      description: propDescription,
                      required: required,
                      values: values
                    });
                  }
                });
              }
            }
            
            // defineProps({ ... }) 对象定义
            else if (path.node.arguments.length > 0 && t.isObjectExpression(path.node.arguments[0])) {
              const propsObject = path.node.arguments[0];
              propsObject.properties.forEach(prop => {
                if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
                  const propName = prop.key.name;
                  let propType = 'any';
                  let required = false;
                  let defaultValue: string | undefined;
                  
                  // 简单类型定义: propName: String
                  if (t.isIdentifier(prop.value)) {
                    propType = CompilerSfcPropertyExtractor.mapVueTypeToString(prop.value.name);
                  }
                  // 对象类型定义: propName: { type: String, required: true, ... }
                  else if (t.isObjectExpression(prop.value)) {
                    prop.value.properties.forEach(propOption => {
                      if (t.isObjectProperty(propOption)) {
                        if (t.isIdentifier(propOption.key) && propOption.key.name === 'type' && t.isIdentifier(propOption.value)) {
                          propType = CompilerSfcPropertyExtractor.mapVueTypeToString(propOption.value.name);
                        }
                        else if (t.isIdentifier(propOption.key) && propOption.key.name === 'required' && 
                                (t.isBooleanLiteral(propOption.value) || t.isIdentifier(propOption.value))) {
                          required = propOption.value.type === 'BooleanLiteral' ? 
                            propOption.value.value : 
                            propOption.value.name === 'true';
                        }
                        else if (t.isIdentifier(propOption.key) && propOption.key.name === 'default') {
                          if (t.isStringLiteral(propOption.value) || t.isNumericLiteral(propOption.value) || 
                              t.isBooleanLiteral(propOption.value)) {
                            defaultValue = JSON.stringify(propOption.value.value);
                          } else {
                            // 对于复杂默认值，获取原始代码
                            defaultValue = scriptContent.substring(
                              propOption.value.start || 0,
                              propOption.value.end || 0
                            );
                          }
                        }
                      }
                    });
                  }
                  
                  // 查找属性描述
                  const propDescription = CompilerSfcPropertyExtractor.findPropDescriptionFromAST(prop, scriptContent);
                  
                  props.push({
                    name: propName,
                    type: propType,
                    description: propDescription,
                    required,
                    defaultValue,
                    values: []
                  });
                }
              });
            }
          }
          
          // 处理withDefaults(defineProps<{...}>(), {...})
          if (t.isIdentifier(path.node.callee) && path.node.callee.name === 'withDefaults' && 
              path.node.arguments.length === 2 && t.isCallExpression(path.node.arguments[0]) && 
              t.isObjectExpression(path.node.arguments[1])) {
            
            const defaultsObject = path.node.arguments[1];
            const defaultValues = new Map<string, string>();
            
            // 提取默认值
            defaultsObject.properties.forEach(prop => {
              if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {
                const propName = prop.key.name;
                let value = scriptContent.substring(
                  prop.value.start || 0,
                  prop.value.end || 0
                );
                defaultValues.set(propName, value);
              }
            });
            
            // 找到defineProps调用并提取类型
            const definePropsCall = path.node.arguments[0];
            if (t.isIdentifier(definePropsCall.callee) && definePropsCall.callee.name === 'defineProps' &&
                definePropsCall.typeParameters && t.isTSTypeParameterInstantiation(definePropsCall.typeParameters)) {
                
              const typeAnnotation = definePropsCall.typeParameters.params[0];
              if (t.isTSTypeLiteral(typeAnnotation)) {
                typeAnnotation.members.forEach(member => {
                  if (t.isTSPropertySignature(member) && t.isIdentifier(member.key)) {
                    const propName = member.key.name;
                    let propType = 'any';
                    let required = true;
                    let values: string[] = [];
                    
                    // 检查可选属性
                    if (member.optional) {
                      required = false;
                    }
                    
                    // 提取类型
                    if (member.typeAnnotation) {
                      propType = scriptContent.substring(
                        member.typeAnnotation.start || 0, 
                        member.typeAnnotation.end || 0
                      ).replace(/^:\s*/, '');

                      // 从类型中提取可能的枚举值
                      if (t.isTSTypeAnnotation(member.typeAnnotation) && 
                          t.isTSUnionType(member.typeAnnotation.typeAnnotation)) {
                        values = CompilerSfcPropertyExtractor.extractEnumValuesFromUnionType(member.typeAnnotation.typeAnnotation, scriptContent);
                      }
                    }
                    
                    // 查找属性描述（从注释）
                    const propDescription = CompilerSfcPropertyExtractor.findPropDescriptionFromAST(member, scriptContent);
                    
                    props.push({
                      name: propName,
                      type: propType,
                      description: propDescription,
                      required: required && !defaultValues.has(propName),
                      defaultValue: defaultValues.get(propName),
                      values: values
                    });
                  }
                });
              }
            }
          }
        },
        
        // 处理Vue 2 Options API的props
        ObjectExpression(path) {
          const parent = path.parent;
          if (t.isObjectProperty(parent) && t.isIdentifier(parent.key) && parent.key.name === 'props') {
            // 使用类型断言处理数组类型
            if (t.isArrayExpression(path.node)) {
              // 处理数组形式的props: ['prop1', 'prop2']
              const arrayNode = path.node as t.ArrayExpression;
              arrayNode.elements.forEach(element => {
                if (element && t.isStringLiteral(element)) {
                  props.push({
                    name: element.value,
                    type: 'any',
                    description: '',
                    required: false,
                    values: []
                  });
                }
              });
            } else {
              // 处理对象形式的props: { prop1: String, prop2: { type: Number, required: true } }
              path.node.properties.forEach(prop => {
                if (t.isObjectProperty(prop) && (t.isIdentifier(prop.key) || t.isStringLiteral(prop.key))) {
                  const propName = t.isIdentifier(prop.key) ? prop.key.name : prop.key.value;
                  let propType = 'any';
                  let required = false;
                  let defaultValue: string | undefined;
                  
                  // 简单类型定义: propName: String
                  if (t.isIdentifier(prop.value)) {
                    propType = CompilerSfcPropertyExtractor.mapVueTypeToString(prop.value.name);
                  }
                  // 对象类型定义: propName: { type: String, required: true, ... }
                  else if (t.isObjectExpression(prop.value)) {
                    prop.value.properties.forEach(propOption => {
                      if (t.isObjectProperty(propOption)) {
                        if (t.isIdentifier(propOption.key) && propOption.key.name === 'type' && t.isIdentifier(propOption.value)) {
                          propType = CompilerSfcPropertyExtractor.mapVueTypeToString(propOption.value.name);
                        }
                        else if (t.isIdentifier(propOption.key) && propOption.key.name === 'required' && 
                                (t.isBooleanLiteral(propOption.value) || t.isIdentifier(propOption.value))) {
                          required = propOption.value.type === 'BooleanLiteral' ? 
                            propOption.value.value : 
                            propOption.value.name === 'true';
                        }
                        else if (t.isIdentifier(propOption.key) && propOption.key.name === 'default') {
                          if (t.isStringLiteral(propOption.value) || t.isNumericLiteral(propOption.value) || 
                              t.isBooleanLiteral(propOption.value)) {
                            defaultValue = JSON.stringify(propOption.value.value);
                          } else {
                            // 对于复杂默认值，获取原始代码
                            defaultValue = scriptContent.substring(
                              propOption.value.start || 0,
                              propOption.value.end || 0
                            );
                          }
                        }
                      }
                    });
                  }
                  
                  // 查找属性描述
                  const propDescription = CompilerSfcPropertyExtractor.findPropDescriptionFromAST(prop, scriptContent);
                  
                  props.push({
                    name: propName,
                    type: propType,
                    description: propDescription,
                    required,
                    defaultValue,
                    values: []
                  });
                }
              });
            }
          }
        }
      });
    } catch (error) {
      console.error('AST解析组件Props失败:', error);
    }
    
    return props;
  }

  /**
   * 提取组件事件
   * @param descriptor Vue SFC描述符
   * @returns 组件事件列表
   */
  public static extractEvents(descriptor: compiler.SFCDescriptor): ComponentEvent[] {
    const events: ComponentEvent[] = [];
    const scriptContent = descriptor.script?.content || descriptor.scriptSetup?.content || '';
    
    if (!scriptContent) {
      return events;
    }

    try {
      // 使用Babel解析脚本内容
      const ast = parse(scriptContent, {
        sourceType: 'module',
        plugins: ['typescript', 'jsx']
      });

      // 收集事件名称和参数
      const emitCalls = new Map<string, ComponentEventArgument[]>();

      // 遍历AST寻找事件定义和调用
      traverse(ast, {
        // 处理Vue 3 Composition API的defineEmits
        CallExpression(path) {
          const callee = path.node.callee;
          // 处理defineEmits(['event1', 'event2'])形式
          if (t.isIdentifier(callee) && callee.name === 'defineEmits' && 
              path.node.arguments.length > 0 && 
              t.isArrayExpression(path.node.arguments[0])) {
            
            const arrayNode = path.node.arguments[0] as t.ArrayExpression;
            arrayNode.elements.forEach(element => {
              if (element && t.isStringLiteral(element)) {
                emitCalls.set(element.value, []);
              }
            });
          }
          
          // 处理emit('event', ...)调用
          else if (t.isIdentifier(callee) && callee.name === 'emit' && 
                   path.node.arguments.length > 0 && 
                   t.isStringLiteral(path.node.arguments[0])) {
            
            const eventName = path.node.arguments[0].value;
            if (!emitCalls.has(eventName)) {
              emitCalls.set(eventName, []);
            }
          }
          // 处理成员表达式的emit调用 - 安全类型检查
          else if (t.isMemberExpression(callee)) {
            const property = callee.property;
            if (t.isIdentifier(property) && property.name === 'emit' &&
                path.node.arguments.length > 0 && 
                t.isStringLiteral(path.node.arguments[0])) {
              
              const eventName = path.node.arguments[0].value;
              if (!emitCalls.has(eventName)) {
                emitCalls.set(eventName, []);
              }
            }
          }
        },
        
        // 处理Vue 2 Options API的事件调用
        MemberExpression(path) {
          const object = path.node.object;
          const property = path.node.property;
          
          if (t.isThisExpression(object) && 
              t.isIdentifier(property) && property.name === '$emit' && 
              t.isCallExpression(path.parent) && 
              path.parent.arguments.length > 0 && 
              t.isStringLiteral(path.parent.arguments[0])) {
            
            const eventName = path.parent.arguments[0].value;
            if (!emitCalls.has(eventName)) {
              emitCalls.set(eventName, []);
            }
          }
        },
        
        // 处理Vue 2 Options API的emits选项
        ObjectExpression(path) {
          const parent = path.parent;
          if (t.isObjectProperty(parent) && 
              t.isIdentifier(parent.key) && 
              parent.key.name === 'emits') {
            
            if (t.isArrayExpression(path.node)) {
              // 处理数组形式的emits: ['event1', 'event2']
              const arrayNode = path.node as t.ArrayExpression;
              arrayNode.elements.forEach(element => {
                if (element && t.isStringLiteral(element)) {
                  emitCalls.set(element.value, []);
                }
              });
            }
          }
        }
      });

      // 从模板中提取事件
      if (descriptor.template?.content) {
        const templateContent = descriptor.template.content;
        // 使用compiler-sfc的compileTemplate来分析模板中的事件
        const { ast: templateAst } = compiler.compileTemplate({
          source: templateContent,
          filename: descriptor.filename,
          id: 'template'
        });

        // 遍历模板AST可以提取更多事件信息，但需要更复杂的处理
        // 这里为简化实现，可以使用简单的正则匹配
        const emitRegex = /\$emit\s*\(\s*['"]([^'"]+)['"]/g;
        let match;
        while ((match = emitRegex.exec(templateContent)) !== null) {
          const eventName = match[1];
          if (!emitCalls.has(eventName)) {
            emitCalls.set(eventName, []);
          }
        }
      }

      // 收集所有事件并查找描述
      for (const [eventName, args] of emitCalls.entries()) {
        // 查找事件描述
        const eventDescription = CompilerSfcPropertyExtractor.findEventDescriptionFromCode(eventName, scriptContent);
        
        events.push({
          name: eventName,
          description: eventDescription,
          arguments: args
        });
      }
    } catch (error) {
      console.error('AST解析组件事件失败:', error);
    }
    
    return events;
  }

  /**
   * 提取组件插槽
   * @param descriptor Vue SFC描述符
   * @returns 组件插槽列表
   */
  public static extractSlots(descriptor: compiler.SFCDescriptor): ComponentSlot[] {
    const slots: ComponentSlot[] = [];
    
    if (!descriptor.template?.content) {
      return slots;
    }

    const templateContent = descriptor.template.content;
    
    try {
      // 使用compiler-sfc的compileTemplate来分析模板中的插槽
      const { ast: templateAst } = compiler.compileTemplate({
        source: templateContent,
        filename: descriptor.filename,
        id: 'template'
      });

      // 由于templateAst的结构复杂，这里使用简化的正则匹配方式
      
      // 查找命名插槽
      const namedSlotRegex = /<slot\s+name=(['"])([^'"]+)\1[^>]*>/g;
      let match;
      while ((match = namedSlotRegex.exec(templateContent)) !== null) {
        const slotName = match[2];
        const slotTag = match[0];
        
        // 检查插槽是否已存在
        const existingSlot = slots.find(s => s.name === slotName);
        if (!existingSlot) {
          // 查找slot上的属性，它们可能是绑定变量
          const bindingRegex = /\s+:([^=]+)=(['"])([^'"]+)\2/g;
          const bindings: ComponentSlotBinding[] = [];
          
          let bindingMatch;
          while ((bindingMatch = bindingRegex.exec(slotTag)) !== null) {
            bindings.push({
              name: bindingMatch[1],
              type: 'any', // 默认类型
              description: '',
            });
          }
          
          // 查找插槽描述
          const slotDescription = CompilerSfcPropertyExtractor.findSlotDescriptionFromTemplate(slotName, templateContent);
          
          slots.push({
            name: slotName,
            description: slotDescription,
            bindings: bindings,
          });
        }
      }
      
      // 查找Vue 3的v-slot语法
      const vSlotRegex = /<template\s+v-slot:([^=>\s]+)[^>]*>/g;
      while ((match = vSlotRegex.exec(templateContent)) !== null) {
        const slotName = match[1];
        
        // 检查插槽是否已存在
        const existingSlot = slots.find(s => s.name === slotName);
        if (!existingSlot) {
          slots.push({
            name: slotName,
            description: '',
            bindings: [],
          });
        }
      }
      
      // 查找默认插槽
      const defaultSlotMatch = templateContent.match(/<slot\s+[^>]*>/);
      if (defaultSlotMatch && !slots.find(s => s.name === 'default')) {
        const slotTag = defaultSlotMatch[0];
        
        // 查找slot上的属性，它们可能是绑定变量
        const bindingRegex = /\s+:([^=]+)=(['"])([^'"]+)\2/g;
        const bindings: ComponentSlotBinding[] = [];
        
        let bindingMatch;
        while ((bindingMatch = bindingRegex.exec(slotTag)) !== null) {
          bindings.push({
            name: bindingMatch[1],
            type: 'any',
            description: '',
          });
        }
        
        // 查找插槽描述
        const slotDescription = CompilerSfcPropertyExtractor.findSlotDescriptionFromTemplate('default', templateContent);
        
        slots.push({
          name: 'default',
          description: slotDescription,
          bindings: bindings,
        });
      }
    } catch (error) {
      console.error('解析组件插槽失败:', error);
    }
    
    return slots;
  }

  /**
   * 从AST中提取属性描述
   * @param node AST节点
   * @param scriptContent 脚本内容
   * @returns 属性描述
   */
  private static findPropDescriptionFromAST(node: any, scriptContent: string): string {
    if (!node.leadingComments || node.leadingComments.length === 0) {
      return '';
    }
    
    // 获取属性上方的注释
    const comment = node.leadingComments[node.leadingComments.length - 1].value;
    return CommentUtils.extractDescription(comment);
  }

  /**
   * 从代码中查找事件描述
   * @param eventName 事件名称
   * @param scriptContent 脚本内容
   * @returns 事件描述
   */
  private static findEventDescriptionFromCode(eventName: string, scriptContent: string): string {
    // 由于AST中难以直接关联事件与注释，我们可以使用更简单的方法
    // 查找事件附近的注释
    const eventPattern = new RegExp(`\\/\\*\\*([\\s\\S]*?)\\*\\/[\\s\\S]*?('|")${eventName}('|")`, 'i');
    const match = eventPattern.exec(scriptContent);
    if (match) {
      return CommentUtils.extractDescription(match[1]);
    }
    return '';
  }

  /**
   * 从模板中查找插槽描述
   * @param slotName 插槽名称
   * @param templateContent 模板内容
   * @returns 插槽描述
   */
  private static findSlotDescriptionFromTemplate(slotName: string, templateContent: string): string {
    // 查找slot标签前的注释
    const slotPattern = slotName === 'default' 
      ? /(<!--((?:[^-]|(?:-(?!->)))*)--->)?\s*<slot\s+[^>]*>/
      : new RegExp(`(<!--((?:[^-]|(?:-(?!->)))*)--->)?\\s*<slot\\s+name=['"']${slotName}['"'][^>]*>`, 's');
    
    const slotMatch = slotPattern.exec(templateContent);
    
    if (slotMatch && slotMatch[1]) {
      // 提取注释内容
      const comment = slotMatch[2];
      if (comment) {
        return comment.trim();
      }
    }
    
    return '';
  }

  /**
   * 从TypeScript联合类型中提取枚举值
   * @param unionType TypeScript联合类型节点
   * @param scriptContent 脚本内容
   * @returns 枚举值数组
   */
  private static extractEnumValuesFromUnionType(unionType: any, scriptContent: string): string[] {
    const values: string[] = [];
    
    if (unionType.types) {
      unionType.types.forEach((type: any) => {
        if (type.type === 'TSLiteralType') {
          if (type.literal.type === 'StringLiteral') {
            values.push(type.literal.value);
          } else if (type.literal.type === 'NumericLiteral') {
            values.push(String(type.literal.value));
          } else if (type.literal.type === 'BooleanLiteral') {
            values.push(String(type.literal.value));
          }
        }
      });
    }
    
    return values;
  }

  /**
   * 映射Vue类型声明到字符串类型
   * @param vueType Vue类型（String, Number等）
   * @returns 映射后的类型字符串
   */
  private static mapVueTypeToString(vueType: string): string {
    switch (vueType.trim()) {
      case 'String': return 'string';
      case 'Number': return 'number';
      case 'Boolean': return 'boolean';
      case 'Array': return 'array';
      case 'Object': return 'object';
      case 'Function': return 'function';
      case 'Date': return 'date';
      case 'Symbol': return 'symbol';
      default: return vueType.toLowerCase();
    }
  }
} 